package academic.emailClient.persistence;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import academic.emailClient.model.entities.Filter;
import academic.emailClient.model.entities.FilterBuilder;

public class FilterFileDAO {
	
	private static String NAME = "name";
	private static String QUERY = "query";
	private static String QUERY_ATTRIBUTE = "queryAttribute";
	private static String DESTINATION_FOLDER_PATH = "destination_folder_path";
	private static String FILTER = "filter";	
	
	/**
	 * Persists a filter as an xml file
	 * @param filter filter object
	 * @return True if the file can be written
	 * @throws RuntimeException Exceptions caused by the use of DOM parser
	 */
	public static boolean write(String path, Filter filter) throws RuntimeException{
		try {						
			
			//Document instatiation
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			
			//Root
			Document document = builder.newDocument();
			Element rootElement = document.createElement(FILTER);
			document.appendChild(rootElement);
			
			//Creates values
			Element name = document.createElement(NAME);
			name.appendChild(document.createTextNode(filter.getName()));
			rootElement.appendChild(name);			
			
			Element query = document.createElement(QUERY);
			rootElement.appendChild(query);
			
			for (String queryAttribute : filter.getQuery()){
				Element queryAttr = document.createElement(QUERY_ATTRIBUTE);
				queryAttr.appendChild(document.createTextNode(queryAttribute));
				query.appendChild(queryAttr);
			}
			
			Element destinationFolderPath = document.createElement(DESTINATION_FOLDER_PATH);
			destinationFolderPath.appendChild(document.createTextNode(filter.getDestinationFolderPath()));
			rootElement.appendChild(destinationFolderPath);
			
			//Transforms the document java with 
			TransformerFactory transFactory = TransformerFactory.newInstance();
			Transformer transformer = transFactory.newTransformer();
			//DOM Parser to convert document
			DOMSource source = new DOMSource(document);
			
			//parsing source to result
			StreamResult result = new StreamResult(new File(path, filter.getName()));
			transformer.transform(source, result);			
			
			return true;
			
		}
		catch (ParserConfigurationException e){
			throw new RuntimeException(e);
		}
		catch (TransformerConfigurationException tce){
			throw new RuntimeException(tce);
		}
		catch (TransformerException te){
			throw new RuntimeException(te);
		}		
	}
	
	/**
	 * Reads a list of filters persisted in a file directory
	 * @return HashMap<filter ID, filter>
	 */
	public static HashMap<String, Filter> read(String path){
		HashMap<String, Filter> filters = new HashMap<String, Filter>();
		File filterDirectory = new File(path);	
		String[] fileNames = filterDirectory.list();
	
		try {
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();		

			
			for (String fileName : fileNames){
				
				File file = new File(path, fileName); 
				Document source = docBuilder.parse(file);
				Element filterInfo = (Element) source.getElementsByTagName(FILTER).item(0);
				
				//Query attributes
				ArrayList<String> query = new ArrayList<String>();
				Element queryAttrsGroup = (Element) filterInfo.getElementsByTagName(QUERY).item(0);
				NodeList queryAttrInfo = queryAttrsGroup.getElementsByTagName(QUERY_ATTRIBUTE);
				for (int i=0; i<queryAttrInfo.getLength(); i++){
					query.add(queryAttrInfo.item(i).getTextContent());
				}
				
				//Filter construction
				FilterBuilder filter = new FilterBuilder();
				Filter readFilter = filter.withName(filterInfo.getElementsByTagName(NAME).item(0).getTextContent())
										  .withQuery(query)
										  .withDestinationFolderPath(filterInfo.getElementsByTagName(DESTINATION_FOLDER_PATH).item(0).getTextContent())
										  .build();
				filters.put(readFilter.getName(), readFilter);
			}
		}
		catch (ParserConfigurationException pce){
			throw new RuntimeException(pce);
		}
		catch (Exception e){
			throw new RuntimeException(e);
		}

		return filters;
	}
		
	/**
	 * Deletes a filter from the persistence source
	 * @param filter filter to delete, should be built
	 * @return True if filter can be deleted
	 */
	public static boolean delete(String path, String filterName){
		File file = new File(path, filterName);
		return file.delete();
	}
	
}
